package com.smartx.app.fragment;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;

import com.smartx.app.R;
import com.smartx.app.SatApp;
import com.smartx.app.dialog.InputPwdDialogFragment;
import com.smartx.app.dialog.LoadingDialog;
import com.smartx.app.dialog.MessageDialog;
import com.smartx.app.model.TransferNonce;
import com.smartx.app.util.DefaultHttpRequest;
import com.smartx.app.util.HttpRequestManager;
import com.smartx.config.Constants;
import com.smartx.core.Wallet;
import com.smartx.core.exception.WalletLockedException;
import com.smartx.crypto.Hex;
import com.smartx.crypto.Key;
import com.smartx.crypto.Native;
import com.smartx.util.ZbarUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

import cn.bertsir.zbar.QRManager;
import okhttp3.Headers;

public class SendFragment extends Fragment implements View.OnClickListener {

    private static final String TAG="transaction";
    private EditText mAmountEditText = null;
    private EditText mAddressEditText = null;
    private ImageButton mScanQrCodeButton = null;
    private Button mSendButton = null;
    private LoadingDialog mLoadingDialog;
    private InputPwdDialogFragment mInputPwdDialogFragment;
    private MessageDialog mMessageDialog;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_send,container,false);
        initView(view);
        return view;
    }

    private void initView(View view) {
        mAmountEditText = view.findViewById(R.id.send_amount);
        mAddressEditText = view.findViewById(R.id.send_to_address);
        mScanQrCodeButton = view.findViewById(R.id.scan_barcode_button);
        mSendButton = view.findViewById(R.id.send_raw_transaction);

        mScanQrCodeButton.setOnClickListener(this);
        mSendButton.setOnClickListener(this);
    }

    @Override
    public void onResume(){
        super.onResume();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.scan_barcode_button:
                //TODO: 弹出摄像头并扫描获取地址
                ZbarUtil.startScan(getActivity(),new QRManager.OnScanResultCallback() {
                    @Override
                    public void onScanSuccess(String result) {
                        if(result != null) {
                            if(!TextUtils.isEmpty(result)) {
                                mAddressEditText.setText(result);
                            }
                        }
                    }

                    @Override
                    public void onScanFailed() {
                        Log.e(TAG,"scan qr code failed");
                    }
                });
                break;
            case R.id.send_raw_transaction:

                //TODO: 地址必须是hex编码的40位数字字母

                //TODO: 金额必须是数字

                showInputPwdDialog(getResources().getString(R.string.please_input_password));

                break;
        }
    }

    private void showLoadingDialog(){
        if(mLoadingDialog == null){
            mLoadingDialog = new LoadingDialog(getActivity());
        }

        mLoadingDialog.show();
    }

    private void dismissLoadingDialog(){
        if(mLoadingDialog == null){
            return;
        }
        mLoadingDialog.dismiss();
    }

    private void showInputPwdDialog(String title){
        if(mInputPwdDialogFragment == null){
            mInputPwdDialogFragment = new InputPwdDialogFragment();
        }

        Bundle bundle = new Bundle();
        bundle.putString("title",title);
        mInputPwdDialogFragment.setArguments(bundle);
        mInputPwdDialogFragment.setTargetFragment(SendFragment.this,Constants.REQUEST_CODE_SEND_TRANSACTION);
        mInputPwdDialogFragment.show(getFragmentManager(),"input password");
    }

    private void dismissInputPwdDialog(){
        if(mInputPwdDialogFragment == null)
            return;

        mInputPwdDialogFragment.dismiss();
    }

    private void showMessageDialog(String message){
        if(mMessageDialog == null){
            mMessageDialog = new MessageDialog();
        }
        Bundle bundle = new Bundle();
        bundle.putString("message",message);
        mMessageDialog.setArguments(bundle);
        mMessageDialog.setTargetFragment(SendFragment.this,Constants.REQUEST_CODE_SHOW_MESSAGE);
        mMessageDialog.show(getFragmentManager(),"input password");
    }

    private void dismissMessageDialog(){
        if(mMessageDialog == null)
            return;

        mMessageDialog.dismiss();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode== Constants.REQUEST_CODE_SEND_TRANSACTION){
            if(resultCode == Activity.RESULT_OK){
                String password= data.getStringExtra(InputPwdDialogFragment.PASSWORD);
                dismissInputPwdDialog();

                showLoadingDialog();
                try{

                    Wallet wallet = SatApp.getInstance().getWallet();
                    wallet.unlock(password);
                    //TODO:不应该直接获取CoinBase为0的key，应该从SatApp里面获取CoinBase
                    Key key = wallet.getAccount(0);
                    Log.d(TAG,"get wallet account 0 " + Hex.encode(key.getPrivateKey()));
                    wallet.lock();
                    Log.d(TAG,"lock wallet send transaction");
                    sendTransaction(key);
                }catch (WalletLockedException e){
                    //提示UI要求重新输入密码
                    Log.e(TAG,"wallet unlock exception");
                    dismissLoadingDialog();
                    showMessageDialog("password error");
                    return;
                }
            }else {
                Log.i(TAG,"input password canceled");
                dismissLoadingDialog();
            }
        }else if(requestCode == Constants.REQUEST_CODE_SHOW_MESSAGE){
            Log.i(TAG,"show message dialog returned");
            dismissMessageDialog();
            return;
        }
        return;
    }

    private void sendTransaction(final Key key) {
        Log.i(TAG,"send raw transaction start get transfer nonce first");
        DefaultHttpRequest request = new DefaultHttpRequest() {
            @Override
            public void onSuccess(String json) {
                Log.i(TAG,"get transfer nonce ok " + json);
                TransferNonce transferNonce = TransferNonce.getTranferNonce(json);
                sendRawTransaction(key,transferNonce);
            }

            @Override
            public String url() {
                return Constants.URL_GET_TRANSFERNONCE;
            }
        };
        HttpRequestManager.manager().get(request);
    }

    private void sendRawTransaction(final Key key,TransferNonce txNonce) {
        Log.i(TAG,"send raw transaction start get transaction raw hash");
        //获取要签名的信息
        String strToSign = getStringToSign(txNonce);
        byte[] firstHash = Native.h256(strToSign.getBytes());
        String firstHashStr = Hex.encode(firstHash)+"1";
        byte[] rawHash = Native.h256(firstHashStr.getBytes());
        String hexRawHash = Hex.encode(rawHash);

        Log.i(TAG,"send raw transaction start sign transaction raw hash");
        //签名交易
        String sign = Hex.encode(key.sign(hexRawHash.getBytes()).toBytes());
        String txJson = getRawTransactionJson(hexRawHash,sign,txNonce);

        Log.i(TAG,"send raw transaction send signed transaction to server");
        //发送交易到rpc server
        DefaultHttpRequest request = new DefaultHttpRequest() {
            @Override
            public void onSuccess(String json) {
                Log.i(TAG,"send raw transaction success " + json);
                dismissLoadingDialog();
                showMessageDialog("send transaction success");
            }

            @Override
            public String url() {
                return Constants.URL_SEND_RAW_TX;
            }
        };
        Map<String,String> headerMaps = new HashMap<>();
        headerMaps.put("Content-Type","application/x-www-form-urlencoded");
        Headers headers = Headers.of(headerMaps);
        request.params().put("raw",txJson);
        HttpRequestManager.manager().post(request,headers);

    }

    private String getStringToSign(TransferNonce txNonce){

        String btype="SMARTX_TXS";
        String to = this.mAddressEditText.getText().toString();
        //TODO:UI上限制用户只能输入数字
        //TODO:amount应该除以10000
        String amount = this.mAmountEditText.getText().toString();
        //BigInteger amount = BigInteger.valueOf(Long.valueOf(amountStr) * 1000);
        String from = SatApp.getInstance().getCoinBaseAddress();
        String address = SatApp.getInstance().getCoinBaseAddress();

        StringBuilder sb = new StringBuilder();
        sb.append("1");
        sb.append("-");
        sb.append(btype);
        sb.append("-");
        sb.append(txNonce.timestamp);
        sb.append("-");
        sb.append(address);
        sb.append("-");
        sb.append(txNonce.nonce);
        sb.append("-");
        sb.append(from);
        sb.append("-");
        sb.append(to);
        sb.append("-");
        sb.append(amount);

        Log.i(TAG,"get string to sign " + sb.toString());

        return sb.toString();
    }

    private String getRawTransactionJson(String hexRawHash,String sign,TransferNonce txNonce){

        String random="1";
        String btype="SMARTX_TXS";
        String to = this.mAddressEditText.getText().toString();
        String amount = this.mAmountEditText.getText().toString();
        String from = SatApp.getInstance().getCoinBaseAddress();
        String address = SatApp.getInstance().getCoinBaseAddress();

        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("hash",hexRawHash);
            jsonObject.put("btype",btype);
            jsonObject.put("timestamp",txNonce.timestamp);
            jsonObject.put("address",address);
            jsonObject.put("nonce",txNonce.nonce);
            jsonObject.put("random",random);
            jsonObject.put("from",from);
            jsonObject.put("to",to);
            jsonObject.put("amount",amount);
            jsonObject.put("sign",sign);
            //String txJson = URLEncoder.encode(jsonObject.toString());
            Log.i(TAG,"get string to sign " + jsonObject.toString());
            return jsonObject.toString();
        } catch (JSONException e) {
            e.printStackTrace();
            return null;
        }
    }
}
